home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / gracil / p10dvr / p10_at.c < prev    next >
C/C++ Source or Header  |  1992-09-07  |  21KB  |  867 lines

  1. /****************************************************************************
  2. *
  3. *            COPYRIGHT 1990,91,92 BY GRACILIS INC.
  4. *
  5. *             623 Palace St.
  6. *             Aurora, Il. 60506
  7. *
  8. *             (708)-801-8800        Office
  9. *             (708)-844-0183        (FAX - Support BBS)
  10. *
  11. * GRACILIS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS 
  12. * SOFTWARE FOR ANY PURPOSE.  
  13. *
  14. * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
  15. * Permission is granted for non-commercial use/distribution only, as long as
  16. * this copyright header is included intact and unaltered.
  17. *
  18. ******************************************************************************/
  19.  
  20.  
  21.  
  22. /************************************************************************
  23. *
  24. *
  25. * File: ipc.c
  26. *
  27. * Rev : 1.0
  28. *
  29. * Description:    
  30. *
  31. *    This File contains routines that implement PackeTen Switch's 
  32. *    inter-processor driver with an interface to KA9Q's TCP/IP suite.
  33. *
  34. *
  35. * Routines: 
  36. *
  37. *    ipc_attach    - Performs attach functions for TCP/IP, i.e.
  38. *                  attach the ipc driver to TCP/IP.
  39. *
  40. *    ipc_raw        - Applications' routine for transmitting
  41. *                  a message via ipc driver.
  42. *
  43. *    ipc_recv    - Applications' routine for receiving a message
  44. *                    from the ipc driver.
  45. *
  46. *    ipc_stat    - Applications' routine for "displaying" the
  47. *                  ipc driver statistics.
  48. *
  49. *    ipc_ioctl    - Set driver parameters.
  50. *
  51. *    ipc_stop    - Stop I/O
  52. *    
  53. *    ipc_init    - Initialize the ipc hardware.
  54. *
  55. *    ipc_txint    - Handles transmit complete interrupts.
  56. *
  57. *    ipc_rxint    - Handles receive complete interrupts.
  58. *
  59. *    ipc_entpt    - Interrupt entry point
  60. *
  61. */
  62.  
  63. /*
  64.     Note: As currently implemented, if the remote side of an IPC
  65.     link stops functioning, and we can not send our data to it,
  66.     eventually, all of NOS buffer memory will be used up.
  67.  
  68.     Some strategy needs be developed to handle this problem...
  69.     It is analagous to a link which cannot transmit due to
  70.     a continuously appearing  CARRIER on frequency.
  71.  
  72. */
  73. #include <stdio.h>
  74. #include <dos.h>
  75. #include "global.h"
  76. #include "pc.h"
  77. #include "config.h"
  78. #include "mbuf.h"
  79. #include "ax25.h"
  80. #include "iface.h"
  81. #include "lapb.h"
  82. #include "proc.h"
  83. #include "trace.h"
  84. #include "netuser.h"
  85. #include "proc.h"
  86. #include "pktdrvr.h"
  87. #include "commands.h"
  88. #include "devparam.h"
  89. #include "gracilis.h"
  90. #include "p10.h"
  91.  
  92. #ifdef OLD_KA9Q
  93. #else
  94. #define    tprintf printf
  95. #endif
  96.  
  97.  
  98. #ifdef PACKETEN_DEBUG
  99. extern long    recvcalls;
  100. extern long    rawcalls;
  101. #endif
  102.  
  103. extern UNI_DCB P10_udcb[];
  104.  
  105.  
  106. extern INTERRUPT (*P10oldvec) __ARGS((void)); /* Old vector contents */
  107. extern int16       P10_vec;        /* Vector number */
  108.  
  109. extern int16    P10Proc_id;        /* The PC is processor 2!!! */
  110.  
  111. extern     IPC     *P10Ipc;
  112. extern    int16    P10Pcport;
  113.  
  114. extern INTERRUPT (*P10handler) __ARGS((void));
  115.  
  116.  
  117. /********************************************************************
  118. *                        IPC_ATTACH                                *
  119. *                                                                  *
  120. * File: ipc.c                                                * 
  121. * Rev : 1.0                                      *
  122. *                                                                  *
  123. ********************************************************************
  124. *
  125. *
  126. * DESCRIPTION: 
  127. * -----------
  128. * Attaches the PackeTen Switch's ipc driver to NOS.
  129. *
  130. * ARGUMENTS:
  131. * ---------
  132. *    All argv's are strings
  133. * argv[0]: hardware type,  "ipc"  
  134. *
  135. * argv[1]: vector, e.g., "2"
  136. *
  137. * argv[2]: "0" = PACKETEN main card
  138. *       "1" = PACKETEN daughter card
  139. *       "2" = IBM PC side of IPC
  140. * argv[3]: interface "NAME"
  141. *
  142. * argv[4]: encap mode
  143. *
  144. * argv[5]: OPTIONAL - IPC memory base address
  145. *
  146. * argv[6]: OPTIONAL - PackeTen control Port address - Default 0x238
  147. *
  148. * argv[7]: OPTIONAL - Tx Queue Depth, num. of tx packets to allow in the 
  149. *              "to be transmitted queue" at one time. 
  150. * argv[8]: OPTIONAL - # of rx buffers to preallocate !!! NOT IMPLEMENTED
  151. *
  152. * argv[9]: OPTIONAL - Ip address
  153. *
  154. * RETURN VALUES:
  155. * -------------
  156. *  0 - success
  157. * -1 - failure, driver not attached and no memory left allocated
  158. *
  159. * GLOBAL INPUTS:
  160. * -------------
  161. *        
  162. * GLOBAL OUTPUTS:
  163. * --------------
  164. *
  165. * FUNCTIONS CALLED:
  166. * ----------------
  167. * tprintf
  168. * calloc
  169. * malloc
  170. * free
  171. *
  172. * IO:
  173. * --
  174. *
  175. *
  176. ******************************************************************/
  177.  
  178.  
  179. int
  180. ipc_attach(argc,argv,p)
  181. int argc;            
  182. char *argv[];
  183. void *p;                    /* new for NOS */
  184. {
  185.     extern struct iface *ifaces;
  186.     struct iface *intfc_p;
  187.     IPC_DCB *sp;
  188.     UNI_DCB *udcbp;
  189.     int devnum, an_ipc_is_attached;
  190.     int32 ipaddr;                /* new for NOS */
  191.     char    i_state;    /* saved state of the interrupt level */
  192.     int    i;        /* gen purpose counter ... etc */
  193.     struct ipcbuf *rxarea;
  194.     long base_addr;
  195.     int16    port;
  196.  
  197.     /* 
  198.      * validate input params 
  199.      */
  200.     if ( argc < 5 )
  201.     {
  202.  
  203.         tprintf("ipc_attach: too few arguments (%d) \r\n", argc);
  204.         tprintf("ipc <vector> <processor (dc|mc)> <name> <mode> [base addr] [ctl addr]\r\n");
  205.         tprintf("             [txQdepth] [rxbufs] [ip addr]\r\n");
  206.         return(-1);
  207.     }
  208.  
  209.  
  210. #ifdef PACKETEN_DEBUG
  211.  
  212.     tprintf("ipc_attach: argument count is %d\n",argc);
  213.     for(i=0;i<argc;i++)
  214.         tprintf("arg #%d: %s\n",i,argv[i]);
  215.     tprintf("\n\n");
  216. #endif
  217.  
  218.     /* set the udcb device # for this processor's ipc */
  219.     devnum = -1;
  220.     if(strcmpi(argv[2],"mc") == 0)   devnum = 0;
  221.     if(strcmpi(argv[2],"dc") == 0)   devnum = 1;
  222.     if(strcmpi(argv[2],"pc") == 0)   devnum = 2;
  223.  
  224.     if(devnum == -1)
  225.     {
  226.         tprintf("ipc_attach err: unknown processor id %s\r\n",argv[2]);
  227.         tprintf("Try 'mc' for PackeTen Main Card or 'dc' for Daughter Card.\n");
  228.         return(-1);
  229.     }
  230.  
  231.     if((devnum) == P10Proc_id)    /* Can't be same as Our local processor*/
  232.     {
  233.         tprintf("ipc_attach err: processor id %s is LOCAL!!!\r\n",argv[2]);
  234.         tprintf("Try 'mc' for PackeTen Main Card or 'dc' for Daughter Card.\n");
  235.         return(-1);
  236.     }
  237.  
  238.  
  239.     if ( if_lookup(argv[3]) != NULLIF )    /* new for NOS */
  240.     {
  241.         tprintf("Interface %s already exists \r\n", argv[3]);
  242.         return(-1);
  243.     }
  244.  
  245.     /* new for NOS, Set the IP address */
  246.     ipaddr = Ip_addr;            /* default value */
  247.     if ( argc >= 10  )
  248.         ipaddr = resolve(argv[9]);
  249.     if ( ipaddr == 0 )
  250.     {
  251.         tprintf(Noipaddr);
  252.         return(-1);
  253.     }
  254.  
  255.     if(argc >= 6)
  256.     {
  257. #ifdef PACKETEN_DEBUG
  258.         tprintf("Base address = %lx\n",(unsigned long)ghtol(argv[5]));
  259. #endif
  260.         P10Ipc = (IPC *)ghtol(argv[5]);
  261.         base_addr = ptol(P10Ipc);
  262.  
  263.         if(    (base_addr != 0x80000000) &&
  264.             (base_addr != 0x90000000) &&
  265.             (base_addr != 0xA0000000) &&
  266.             (base_addr != 0xC0000000) &&
  267.             (base_addr != 0xD0000000) &&
  268.             (base_addr != 0xE0000000) 
  269.           )
  270.         {
  271.             tprintf("Bad IPC base address specified: %lx\n",base_addr);
  272.             return(-1);
  273.         }
  274.  
  275.  
  276.     }
  277.  
  278.     /* Did the user specify a port address? */
  279.     if(argc >= 7)
  280.     {
  281.         if((port = atoi(argv[6])) == 0)
  282.         {
  283.             tprintf("Illegal Control Port address specified: %s\n",argv[6]);
  284.             return(-1);
  285.         }
  286.         else P10Pcport = port;
  287.     }
  288.  
  289.     /* Gracilis 7/25/92 DGL */
  290.     /* Be sure to enable the dual port RAM for release 2 CPU's */
  291.     ipc_mapin(P10Pcport);
  292.  
  293.  
  294.     udcbp = &P10_udcb[devnum];    /* dev num is index number!!! */
  295.  
  296.     /* See if already attached */
  297.     if ( udcbp->attached )
  298.     {
  299.         tprintf("ipc_attach error: IPC channel already attached; interface is %s\n", argv[3]); 
  300.         return(-1);
  301.     }
  302.  
  303.  
  304.     /* 
  305.      * try to allocate necessary memory 
  306.      */
  307.  
  308.     intfc_p = (struct iface *)calloc(1,sizeof(struct iface));
  309.     if ( intfc_p !=  (struct iface *)0 )
  310.     {
  311.         intfc_p->name = malloc((unsigned)strlen(argv[3])+2);
  312.         if (intfc_p->name != NULLCHAR )    
  313.         {
  314.             intfc_p->hwaddr = NULL;
  315.         }
  316.         else
  317.         {
  318.             free(intfc_p);
  319.             tprintf("ipc_attach error: no memory for interface name, size 7 bytes, interface %s", argv[3]);
  320.             return(-1);
  321.         }
  322.     }
  323.     else
  324.     {
  325.         tprintf("ipc_attach error: no memory for interface struct, size of %d, interface %s", sizeof(struct iface),argv[3]);
  326.         return(-1);
  327.     }
  328.  
  329.     /* allocate and clear the device control block */
  330.     sp = (IPC_DCB *)calloc(1,sizeof(IPC_DCB));
  331.     if ( sp == (IPC_DCB *)0 )
  332.     {
  333.         free(intfc_p->name);
  334.         free(intfc_p);
  335.         tprintf("ipc_attach error: no memory for device control block structure, size of %d, interface %s", sizeof(IPC_DCB),argv[3]);
  336.         return(-1);
  337.     }
  338.  
  339.  
  340.     /* this needs to be done BEFORE the buffers are allocated... */
  341.     /* DGL 4/17/90 */
  342.  
  343.     /* 7/25/92 DGL */
  344.     /* intfc_p->type = CL_AX25; */
  345.     /* attempt to set the encapsulation type */
  346.     /* This needs to be done before we preallocate */
  347.     /* receive buffers, since we have to indicate the */
  348.     /* encap type in the buffers for later use. */
  349.     /* Only allow type "IPC" or "AX25" */
  350.     if(((strcmpi(argv[4],"ax25") != 0) && 
  351.         (strcmpi(argv[4],"ipc") != 0)) ||
  352.        (setencap(intfc_p,argv[4]) != 0))
  353.     {
  354.         /* An invalid encap mode was specified... */
  355.         /* Just print a message and exit */
  356.         tprintf("Illegal mode specification: %s\n",argv[4]);
  357.         free(intfc_p->name);
  358.         free(intfc_p);
  359.         free(sp);
  360.         return(-1);
  361.     }
  362.  
  363.     /* preallocate rx buffers */
  364.     /* set the rxavailbufs parameter */
  365.     if ( argc >= 9 )
  366.         sp->rxavailbufs = atoi(argv[8]);
  367.     else
  368.         sp->rxavailbufs = IPC_BUF_CNT + 1;
  369.  
  370.     /* get the requested rx pre-allocated mbuf's */
  371.     sp->rxavailq = NULLBUF;
  372.  
  373.  
  374.     f_getavail(&(sp->rxavailq), (sp->rxavailbufs), IPC_BUF_SIZE, &(sp->rxavailcount), intfc_p, (bool)FALSE); 
  375.  
  376. #ifdef PACKETEN_DEBUG
  377. tprintf("ipc_attach: rxavailbufs is %d, rxavailcount is %d\n", sp->rxavailbufs, sp->rxavailcount); 
  378. #endif
  379.  
  380.     if(sp->rxavailcount < sp->rxavailbufs)
  381.     {
  382.         tprintf("ipc_attach: Insufficient Memory to preallocate rx buffers...\n");
  383.         free(intfc_p->name);
  384.         free(intfc_p);
  385.  
  386.         /* Now free all successfully allocated buffers... */    
  387.         while((sp->rxbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount)) != NULLBUF)
  388.             free(sp->rxbufp);
  389.  
  390.         free(sp);
  391.         return(-1);
  392.     }
  393.     
  394.     /* setup the receive buffer pointer */
  395.     sp->rxbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount);
  396.  
  397.     /*
  398.      * Setup the interface structure and link it to the list
  399.      * of interface structures.
  400.      */
  401.     /* the Ascii name of the driver unit */
  402.     strcpy(intfc_p->name,argv[3]);
  403.  
  404.     /* fill in this "Unit's" driver control block */
  405.  
  406.     intfc_p->mtu = (IPC_BUF_SIZE - MAX_AX25_HDR_LEN);
  407.     intfc_p->ioctl =  ipc_ioctl;
  408.     intfc_p->raw = ipc_raw;
  409.     intfc_p->stop = ipc_stop;
  410.     intfc_p->dev = devnum;
  411.     intfc_p->addr = ipaddr;
  412.  
  413.     /* new for NOS Mycall replaces (char *)&mycall */
  414.     intfc_p->hwaddr = mallocw(AXALEN);
  415.     memcpy(intfc_p->hwaddr,Mycall,AXALEN);  
  416.  
  417.  
  418.     /* lastly, but very importantly, put in the LL of interfaces */
  419.     intfc_p->next = Ifaces;
  420.     Ifaces = intfc_p;
  421.  
  422.  
  423.     /* 
  424.      * Initialize the unit's driver control block 
  425.      */
  426.     sp->iface = intfc_p;        /* new for NOS - save the iface */
  427.                     /* address for use in queueing */
  428.                     /* mbufs onto Hopper */
  429.     sp->destproc = (devnum);
  430.     sp->xmtq = (struct drvbuf *)0;
  431.     sp->xmtqtail = (struct drvbuf *)0;
  432.     sp->freem = (struct drvbuf *)0;
  433.  
  434.     if ( argc >= 8  )
  435.         sp->txq_depth = atoi(argv[7]);
  436.     else
  437.         sp->txq_depth = IPC_TX_DEPTH_DEFAULT;
  438.  
  439.  
  440.     /* no need to init stats because calloc zero-ed the sp */
  441.     sp->intcnt = 0;
  442.     sp->txcnt = 0;
  443.  
  444.     /*
  445.      *  Now for the hardware dependent initializations.
  446.      *
  447.      *  intfc_p->dev tells which unit/dev
  448.       *
  449.      */
  450. #ifdef PACKETEN_DEBUG
  451.     tprintf("ipc_attach: intfc_p->dev = %x config IPC HW \r\n", intfc_p->dev);
  452. #endif
  453.  
  454.  
  455.  
  456.     /* HERE WE start DIDDLING the actual hardware regs... */
  457.     /* So to be safe, NO ints... */    
  458.     i_state = dirps();
  459.  
  460.     /* reset all possible pending ints for IPC */
  461.     clrint302dc();
  462.     clrint302mc();
  463.  
  464.     switch(P10Proc_id)
  465.     {
  466.         case    0: switch(sp->destproc)
  467.                {
  468.                 case    1: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[0].proc_buf[0];
  469.                        sp->rxcontrol = (uchar *)&P10Ipc->proc[0].control[0];
  470.                        sp->txcontrol = (uchar *)&P10Ipc->proc[1].control[0];
  471.                        sp->txarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[0];
  472.                        break;
  473.  
  474.                 case    2: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[0].proc_buf[1];
  475.                        sp->rxcontrol = (uchar *)&P10Ipc->proc[0].control[1];
  476.                        sp->txcontrol = (uchar *)&P10Ipc->proc[2].control[0];
  477.                        sp->txarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[0];
  478.                        break;
  479.  
  480.                 default:   break;
  481.                }
  482.                break;
  483.  
  484.         case    1: switch(sp->destproc)
  485.                {
  486.                 case    0: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[0];
  487.                        sp->rxcontrol = (uchar *)&P10Ipc->proc[1].control[0];
  488.                        sp->txcontrol = (uchar *)&P10Ipc->proc[0].control[0];
  489.                        sp->txarea = (struct ipcbuf *)P10Ipc->proc[0].proc_buf[0];
  490.                        break;
  491.  
  492.                 case    2: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[1];
  493.                        sp->rxcontrol = (uchar *)&P10Ipc->proc[1].control[1];
  494.                        sp->txcontrol = (uchar *)&P10Ipc->proc[2].control[1];
  495.                        sp->txarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[1];
  496.                        break;
  497.  
  498.                 default:   break;
  499.                }
  500.                break;
  501.  
  502.         case    2: switch(sp->destproc)
  503.                {
  504.                 case    0: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[0];
  505.                        sp->rxcontrol = (uchar *)&P10Ipc->proc[2].control[0];
  506.                        sp->txcontrol = (uchar *)&P10Ipc->proc[0].control[1];
  507.                        sp->txarea = (struct ipcbuf  *)P10Ipc->proc[0].proc_buf[1];
  508.                        break;
  509.  
  510.                 case    1: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[1];
  511.                        sp->rxcontrol = (uchar *)&P10Ipc->proc[2].control[1];
  512.                        sp->txcontrol = (uchar *)&P10Ipc->proc[1].control[1];
  513.                        sp->txarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[1];
  514.                        break;
  515.  
  516.                 default:   break;
  517.                }
  518.                break;
  519.  
  520.  
  521.         default    :    tprintf("Invalid processor ID!!!\n");
  522.                 break;
  523.     }
  524.  
  525.  
  526.  
  527.     /* Initialize IPC RX buffer descriptors */
  528.  
  529.     rxarea = sp->rxarea;
  530.  
  531. #ifdef PACKETEN_DEBUG
  532.     restore(i_state);
  533.     tprintf("rxarea's at:\n");
  534. #endif
  535.     for(i=0;i<IPC_BUF_CNT;i++)
  536.     {
  537. #ifdef PACKETEN_DEBUG
  538.     tprintf("%d at %lx;  ",i, &rxarea[i]);
  539. #endif
  540.         /* mark the buffers inactive */
  541.         rxarea[i].active = (unsigned char)FALSE;
  542.         rxarea[i].msbcnt = (unsigned char)0;
  543.         rxarea[i].lsbcnt = (unsigned char)0;
  544.     }
  545. #ifdef PACKETEN_DEBUG
  546.     tprintf("\n");
  547.     fflush(stdout);
  548.     i_state = dirps();
  549. #endif
  550.     an_ipc_is_attached = FALSE;
  551.                 /* 0,1,2 are IPC chan/dev */
  552.     for (i=0; i<P10_MAXIPC; i++)        
  553.         if (P10_udcb[i].type == IPC_LINK) an_ipc_is_attached = TRUE;
  554.  
  555.  
  556.     /* only set the vector if no IPC link is attached */
  557.     if ( an_ipc_is_attached == FALSE )
  558.     {
  559.         /* tell other processors this processor is talking */
  560.         P10Ipc->active[P10Proc_id] = TRUE;
  561.  
  562.         /* Save old vector and write new vector */
  563.         P10_vec = htoi(argv[1]);
  564.         P10oldvec = getirq(P10_vec);
  565.  
  566.         /* Write ipc's interrupt vector */
  567.         if (setirq(P10_vec, P10handler) == -1)
  568.         {
  569.             tprintf("ipc_attach err:IRQ %u out of range\n",P10_vec);
  570.             free(intfc_p->name);
  571.             free(intfc_p);
  572.             /* Now free all successfully allocated buffers... */    
  573.             while ( (sp->rxbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount)) != NULLBUF)
  574.                 free(sp->rxbufp);
  575.  
  576.             free(sp);
  577.             restore(i_state);
  578.             return(-1);
  579.         }
  580.     }
  581.  
  582.     /* send control msg to other end, tell him I reset my ipc link */
  583.  
  584. #ifdef PACKETEN_DEBUG
  585.     restore(i_state);
  586.     tprintf("sp->txcontrol = %lx\n",sp->txcontrol);
  587.     fflush(stdout);
  588.     i_state = dirps();
  589. #endif
  590.     *sp->txcontrol = IPC_RESET;
  591.     sp->txindex = sp->rxindex = 0;    
  592.     *sp->rxcontrol = 0;
  593.  
  594.     /* force an interrupt to destination processor, to make him see */
  595.     /* my control message */
  596.  
  597.     /* If the destination is the "Main Card"... */
  598.  
  599.     if(sp->destproc == 0) 
  600.         int302mc();
  601.     else      /* otherwise interrupt daughter 302 card */
  602.         int302dc();
  603.  
  604.     /* 
  605.      *  Universal Driver Control Block and 
  606.      *  Vector related initializations
  607.      */
  608.     udcbp->attached = TRUE;
  609.     udcbp->type = IPC_LINK;
  610.  
  611.     /* set address of the unit's driver control block */
  612.     udcbp->dcbp = (char *)sp;
  613.  
  614.     /* enable general ints */
  615.     restore(i_state);
  616.  
  617.     /* new for NOS - start the two processes needed by the */
  618.     /* sync driver; one is for getting pre-allocated buffers */
  619.     /* the other is for kicking the transmitter after its */
  620.     /* timer has expired or when it needs a transmitted */
  621.     /* message free-ed.  P.S. must do after attached set to TRUE */
  622. #ifdef PACKETEN_DEBUG
  623.     tprintf("ipc_attach: calling newproc for ipc_rxavget \n");
  624. #endif
  625.     sp->rxavproc = newproc("ipc rxavget",150,ipc_rxavget,devnum,NULL,NULL,0);
  626.  
  627. #ifdef PACKETEN_DEBUG
  628.     tprintf("ipc_attach: calling newproc for ipc_freetx \n");
  629. #endif
  630.     sp->freetxproc = newproc("ipc freetx",150,ipc_freetx,devnum,NULL,NULL,0);
  631.  
  632.  
  633.     /* DONE */
  634. #ifdef PACKETEN_DEBUG
  635.     tprintf("ipc_attach: All done!!! \n");
  636. #endif
  637.  
  638.     if ( an_ipc_is_attached == FALSE )
  639.         maskon(P10_vec);
  640.  
  641.     return(0);
  642.  }
  643. /*
  644.  * End of ipc_attach()
  645.  ******************************************************************/
  646.  
  647. /* 
  648.  * Display a PackeTen Switch Inter-Processor Communications channel's 
  649.  * statistics.
  650.  */
  651. int
  652. doipcstat(argc,argv,p)
  653. int argc;            
  654. char *argv[];
  655. void *p;                    /* new for NOS */
  656. {
  657. IPC_DCB *dcbp;
  658. UNI_DCB *udcbp;
  659. int16 dev;
  660.  
  661.     /* Header for the IPC channel's on the card */
  662.     tprintf("\n          PackeTen Switch Inter-Processor Comm Channel Statistics\n\n");
  663.     tprintf("Name/To   RxPacks   RxNoBufs   TxPacks    TxFlush   IntCnt    TxqDepth  RxAvail\n");
  664.     tprintf("-------  ---------  --------  ---------  --------  ---------  --------  -------\n");
  665.  
  666.     for (dev=0, udcbp = &P10_udcb[0]; dev < P10_MAXIPC; udcbp++, dev++) 
  667.     {
  668.         if ( udcbp->type == IPC_LINK )
  669.         {
  670.             dcbp = (IPC_DCB *)udcbp->dcbp;
  671.  
  672. /*            tprintf("%4s/%2s  %9.9d  %8.8ld  %9.9ld  %8.8ld  %9.9ld  %8.8ld  %7.7ld\n", 
  673. */
  674.             tprintf("%4s/%2s  %#9lu  %#8u  %#9lu  %#8u  %#9lu  %#8u  %#7u\n", 
  675.  
  676.                    dcbp->iface->name, 
  677.                    ((dev == 5)?"MC": (dev == 6)?"DC" : "PC"),
  678.                    dcbp->rxpackcnt,
  679.                    dcbp->nobufs,
  680.                    dcbp->txpackcnt,
  681.                    dcbp->txflush,
  682.                    dcbp->intcnt,
  683.                    dcbp->txq_depth,
  684.                    dcbp->rxavailcount);
  685.         }
  686.         
  687.     }   /* end of for loop */
  688.  
  689.     tprintf("\n");
  690.     return(0);
  691. }
  692.  
  693.  
  694. /* Subroutine to set kiss params in channel tables */
  695. int32
  696. ipc_ioctl(iface,cmd,set,val)
  697. struct iface *iface;
  698. int cmd;
  699. int set;
  700. int32 val;
  701. {
  702.     IPC_DCB *dcbp;
  703.  
  704.     dcbp = (IPC_DCB *)P10_udcb[iface->dev].dcbp;
  705.  
  706.     switch(cmd){
  707.     case PARAM_RXBUFS:
  708.         if(set)
  709.         {
  710.             dcbp->rxavailbufs = (int16)val;
  711.  
  712.             /* signal the process which */
  713.             /* allocates the rx buffers */
  714.             psignal(&ipc_bufpp[dcbp->destproc],1);
  715.         }
  716.  
  717.         return dcbp->rxavailbufs;
  718.  
  719.     case PARAM_TXQMAX:
  720.         if(set)
  721.             dcbp->txq_depth = (int16)val;
  722.         return dcbp->txq_depth;
  723.  
  724.     }
  725.     return -1;
  726. }
  727.  
  728. /* 
  729.  *  Stop I/O
  730.  */
  731. int
  732. ipc_stop(intfcp)
  733. struct iface *intfcp;
  734. {
  735. IPC_DCB  *sp;
  736. int16 dev;
  737. UNI_DCB *udcbp;
  738. int16    i_state, i, an_ipc_is_attached;
  739. struct drvbuf *xbufp, *tmpptr;
  740. struct mbuf *tmpmbufp;
  741.  
  742.     dev = intfcp->dev;
  743.     udcbp = &P10_udcb[dev];        /* dev num is index number!!! */
  744.  
  745.     if ( udcbp->attached != TRUE )
  746.     {
  747.         tprintf("ipc_stop err: Device already stopped/de-attached!!\n");
  748.         return(0);
  749.     }
  750.  
  751.           sp = (IPC_DCB *)P10_udcb[dev].dcbp;
  752.  
  753.     /* Turn off interrupts */
  754.     i_state = dirps();
  755.  
  756.     /* mark ipc as available - do it now for if below */
  757.     udcbp->attached = FALSE;
  758.     udcbp->type = 0;
  759.     udcbp->dcbp = NULL;
  760.  
  761.  
  762.     an_ipc_is_attached = FALSE;
  763.     for (i=0; i<P10_MAXIPC; i++)
  764.         if (P10_udcb[i].type == IPC_LINK)
  765.             an_ipc_is_attached = TRUE;
  766.  
  767.     /* when both IPC interfaces are stopped - tell other */
  768.     /* processors' this processor ain't talking */
  769.     if ( an_ipc_is_attached == FALSE )
  770.     {
  771.         /* tell the other processors this processor's IPC */
  772.         /* is closed */
  773.         P10Ipc->active[P10Proc_id] = FALSE;
  774.  
  775.         /* Turn off interrupts */
  776.         maskoff(P10_vec);
  777.  
  778.         /* Restore interrupt vector used by IPC handler */
  779.         setirq(P10_vec, P10oldvec); 
  780.     }
  781.  
  782.     restore(i_state);
  783.  
  784.     /* kill off the support processes */
  785.     /* so they don't allocate memory */
  786.     /* whils't we're freeing it */
  787.  
  788.     killproc(sp->rxavproc);
  789.     killproc(sp->freetxproc);
  790.  
  791.  
  792.     /* 
  793.      * Flush all buffers and queue's
  794.        */
  795.  
  796.  
  797.     /* free preallocated rx buffers on the rx available queue */    
  798.  
  799.     while((tmpmbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount)) != NULLBUF)
  800.         free(tmpmbufp);
  801.  
  802.     /* free up any pending transmit buffers... */
  803.     while(sp->xmtq != (struct drvbuf *)0 )
  804.     {
  805.         tmpptr = sp->xmtq->next;
  806.         free(sp->xmtq);
  807.         sp->xmtq = tmpptr;
  808.     }
  809.  
  810.     /* Free any previously sent frames, which are in the waiting to be */
  811.     /* free'd queue */
  812.  
  813.     /* disable ints here to get queue head... */
  814.     i_state = dirps();            /* seems unecessary */
  815.     xbufp = sp->freem;
  816.     sp->freem = (struct drvbuf *)0;
  817.     restore(i_state);
  818.  
  819.     /* Here xbufp is a "to be free'd"  */
  820.     /* queue pointer" */
  821.     /* now free memory of all the xmitted messages */
  822.     while ( xbufp != (struct drvbuf *)0 )
  823.     {
  824.         tmpptr = xbufp->next;
  825.         free((char *)xbufp);
  826.         xbufp = tmpptr;
  827.     }
  828.  
  829.  
  830.     /*
  831.      * Deallocate other driver related memory structures 
  832.      */
  833.     if ( sp->rxbufp != NULLBUF )
  834.          free(sp->rxbufp);
  835.     free(sp);
  836.  
  837.     return(0);
  838. }
  839.  
  840. /* Convert hex-ascii to integer */
  841. static long int
  842. ghtol(s)
  843. char *s;
  844. {
  845.     long int i = 0;
  846.     char c;
  847.  
  848.     while((c = *s++) != '\0'){
  849.         if(c == 'x')
  850.             continue;    /* allow 0x notation */
  851.         if(c == ':')
  852.             continue;    /* allow : for seg:offset notation */
  853.         if('0' <= c && c <= '9')
  854.             i = (i * 16) + (c - '0');
  855.         else if('a' <= c && c <= 'f')
  856.             i = (i * 16) + (c - 'a' + 10);
  857.         else if('A' <= c && c <= 'F')
  858.             i = (i * 16) + (c - 'A' + 10);
  859.         else
  860.             break;
  861.     }
  862.     return i;
  863. }
  864.  
  865.